package ch.fhnw.qualiscan.core.libraries;

import java.io.Serializable;
import java.net.URL;
import java.util.ArrayList;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.fhnw.qualiscan.ApplicationData;
import ch.fhnw.qualiscan.core.Controller;
import ch.fhnw.qualiscan.core.helpers.ControllerLoader;

import com.vaadin.terminal.DownloadStream;
import com.vaadin.terminal.URIHandler;
import com.vaadin.ui.UriFragmentUtility;
import com.vaadin.ui.UriFragmentUtility.FragmentChangedEvent;
import com.vaadin.ui.UriFragmentUtility.FragmentChangedListener;
import com.vaadin.ui.Window;

import eu.livotov.tpt.TPTApplication;

@SuppressWarnings("serial")
public class LoaderLibrary implements FragmentChangedListener, Serializable{
	
	Logger logger = LoggerFactory.getLogger("LoaderLibrary");
	
	
	private Window mainWindow;
	
	private UriFragmentUtility uriHandler;
	private ControllerLoader controllerLoader = new ControllerLoader();
	
	private ApplicationData appData;
	
	private ArrayList<String> currentUrlFragments = new ArrayList<String>();
	private ArrayList<String> oldUrlFragments = new ArrayList<String>();
	
	
	public LoaderLibrary() {}
	
	/**
	 * This function takes care of the browser history. A history listener is attached to the main window. The fragments are set to ""
	 */
	public void initLibrary() {
		

		mainWindow = TPTApplication.getCurrentApplication().getMainWindow();
		appData = (ApplicationData) mainWindow.getData();
		
		uriHandler = new UriFragmentUtility();
		uriHandler.addListener(this);
		mainWindow.addComponent(uriHandler);
		
		initUriHandler();
		
		
	}

	/**
	 * fragmentChanged gets called each time the parameter changes.
	 */
	public void fragmentChanged(FragmentChangedEvent source) {
		
		logger.info("URL changed to: "+ source.getUriFragmentUtility().getFragment());
		
		String[] urlTokens = source.getUriFragmentUtility().getFragment().split("/");
		
		currentUrlFragments.clear();
		
		for (int i = 0; i < urlTokens.length; i++) {
			currentUrlFragments.add(urlTokens[i]);
		}

		boolean controllerChanged = false;
		/*
		 * Compare old and new url and call the appropriate Methods
		 */
		//First check special fragment 0 for controller load
		if (currentUrlFragments.size() > 0) {
		
			if (oldUrlFragments.size() == 0) {
				controllerLoader.loadController(currentUrlFragments.get(0));
			}
			else {
				if (!currentUrlFragments.get(0).equals(oldUrlFragments.get(0))) {
					controllerLoader.loadController(currentUrlFragments.get(0));
					controllerChanged = true;
				}
			}			
		}
		
		//Then compare rest of the fragments
		for (int j = currentUrlFragments.size()-1; j >= 1 ; j--) {
			if (oldUrlFragments.size() > j) {
				if (!currentUrlFragments.get(j).equals(oldUrlFragments.get(j))) {
					if (appData.getCurrentController() != null) {
						appData.getCurrentController().fragmentChanged(j, currentUrlFragments.get(j));
						logger.info("Fragment "+j+" changed to "+currentUrlFragments.get(j)+"");
					}
				}
				else {
					if (controllerChanged == true) {
						appData.getCurrentController().fragmentChanged(j, currentUrlFragments.get(j));
					}
				}
			}
			else {
				if (appData.getCurrentController() != null) {
					appData.getCurrentController().fragmentChanged(j, currentUrlFragments.get(j));
					logger.info("Fragment "+j+" changed to "+currentUrlFragments.get(j)+"");
				}
			}
		}
		
		
		oldUrlFragments.clear();
		for (int g = 0; g < currentUrlFragments.size(); g++) {
			oldUrlFragments.add(currentUrlFragments.get(g));
		}
		
		
	}
	
	public void setUrlFragment(int fragmentId, String fragment) {
		if (fragment != null) {
			String url = "";
			
			int forEnd = 0;
			
			if (fragmentId > currentUrlFragments.size()) {
				forEnd = fragmentId;
			}
			else {
				forEnd = currentUrlFragments.size();
			}
			
			for (int i = 0; i < forEnd; i++) {
				if (i == fragmentId) {
					url += fragment;
				}
				else {
					if (i < currentUrlFragments.size() && currentUrlFragments.get(i) != null) {
						url += currentUrlFragments.get(i);
					}
					else {
						url += "";
					}
				}
				
				if (i != forEnd-1) {
					url += "/";
				}
			}
			
			setUrl(url);
		}
	}
	
	public void setUrl(String url) {
		uriHandler.setFragment(url, true);
	}
	
	/**
	 * 
	 * @param fragment
	 * @return
	 */
	public String getUrlFragment(int fragment) {
		if (currentUrlFragments.get(fragment) == null) {
			return null;
		}
		else {
			return currentUrlFragments.get(fragment);
		}
	}
	
	public void initUriHandler() {
		
		URIHandler uriHandler = new URIHandler() {
			public DownloadStream handleURI(URL context, String relativeUri) {
				
				return null;
			}

		};
		mainWindow.addURIHandler(uriHandler);
	}

	
}
